/**************************************************************************************
 *
 * @(#) FileUtil.java
 * @Package com.jgdt.jgdtkasannong_university_gene_backend.utils.file
 **************************************************************************************/
package com.jgdt.jgdtkasannong_university_gene_backend.utils.file;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;

/**
 * @description: 操作文件 工具类
 * @author: huangAn
 * @createDate: 2025/04/27
 */
@Slf4j
public class FileUtil {
    /**
     * 删除指定目录下的所有文件（保留目录本身）
     *
     * @param dirPath 目录路径（如："/var/www/temp" 或 "C:\\uploads"）
     * @throws IOException 如果目录不存在或删除失败
     */
    public static void deleteAllFilesInDir(String dirPath) {
        try {
            Path dir = Paths.get(dirPath);
            // 安全检查：确保路径存在且是目录
            if (!Files.exists(dir)) {
                log.error("目录不存在:" + dirPath);
                return;
            }
            if (!Files.isDirectory(dir)) {
                log.error("目录不存在:" + dirPath);
                return;
            }
            // 遍历并删除文件（使用try-with-resources确保Stream关闭）
            try (Stream<Path> files = Files.list(dir)) {
                files.forEach(file -> {
                    try {
                        if (Files.isRegularFile(file)) {
                            Files.delete(file);
                            log.debug("已删除文件: " + file); // 生产环境建议改用日志
                        }
                    } catch (IOException e) {
                        log.error("删除文件失败:" + file, e.getMessage());
                        return;
                    }
                });
            }
        } catch (Exception e) {
            log.error("deleteAllFilesInDir,err:" + e.getMessage());
        }
    }

    /**
     * 删除指定目录下的所有文件（保留目录本身），可排除指定文件
     *
     * @param dirPath  目录路径（如："/var/www/temp" 或 "C:\\uploads"）
     * @param excludes 排除规则（支持完整文件名如"logo.png" 或 扩展名如"*.jpg"）
     * @throws IOException 如果目录不存在或删除失败
     */
    public static void deleteAllFilesInDir(String dirPath, String... excludes) {
        try {
            Path dir = Paths.get(dirPath);

            // 安全检查
            if (!Files.exists(dir) || !Files.isDirectory(dir)) {
                log.error("目录不存在或不是有效目录: " + dirPath);
                return;
            }

            // 将排除规则转为Set提高查询效率
            Set<String> excludeRules = new HashSet<>(Arrays.asList(excludes));

            try (Stream<Path> files = Files.list(dir)) {
                files.forEach(file -> {
                    try {
                        if (Files.isRegularFile(file)) {
                            String fileName = file.getFileName().toString();

                            // 检查是否在排除名单
                            if (shouldExclude(fileName, excludeRules)) {
                                log.debug("跳过受保护文件: " + fileName);
                                return;
                            }

                            Files.delete(file);
                            log.debug("已删除文件: " + fileName);
                        }
                    } catch (IOException e) {
                        log.error("删除文件失败 [" + file + "]: " + e.getMessage());
                    }
                });
            }
        } catch (IOException e) {
            log.error("目录遍历异常: " + e.getMessage());
        }
    }

    /**
     * 删除指定目录下的所有文件（保留目录本身），可排除指定文件
     *
     * @param dirPath  目录路径（如："/var/www/temp" 或 "C:\\uploads"）
     * @param excludes 排除规则（支持完整文件名如"logo.png" 或 扩展名如"*.jpg"）
     * @throws IOException 如果目录不存在或删除失败
     */
    public static void deleteAllFilesInDir(String dirPath, List<String> excludes) {
        try {
            Path dir = Paths.get(dirPath);

            // 安全检查
            if (!Files.exists(dir) || !Files.isDirectory(dir)) {
                log.error("目录不存在或不是有效目录: " + dirPath);
                return;
            }

            // 将排除规则转为Set提高查询效率
            Set<String> excludeRules = new HashSet<>(excludes);

            try (Stream<Path> files = Files.list(dir)) {
                files.forEach(file -> {
                    try {
                        if (Files.isRegularFile(file)) {
                            String fileName = file.getFileName().toString();

                            // 检查是否在排除名单
                            if (shouldExclude(fileName, excludeRules)) {
                                log.debug("跳过受保护文件: " + fileName);
                                return;
                            }

                            Files.delete(file);
                            log.debug("已删除文件: " + fileName);
                        }
                    } catch (IOException e) {
                        log.error("删除文件失败 [" + file + "]: " + e.getMessage());
                    }
                });
            }
        } catch (IOException e) {
            log.error("目录遍历异常: " + e.getMessage());
        }
    }

    /**
     * 判断文件是否需要排除
     */
    private static boolean shouldExclude(String fileName, Set<String> rules) {
        // 处理大小写不敏感
        String lowerFileName = fileName.toLowerCase();

        for (String rule : rules) {
            String lowerRule = rule.toLowerCase();

            // 处理扩展名排除（如 *.jpg）
            if (lowerRule.startsWith("*.")) {
                String requiredExt = lowerRule.substring(1); // 变成 .jpg
                int extIndex = lowerFileName.lastIndexOf('.');
                String fileExt = (extIndex != -1) ? lowerFileName.substring(extIndex) : "";

                if (fileExt.equals(requiredExt)) {
                    return true;
                }
            }
            // 完整文件名匹配
            else if (lowerFileName.equals(lowerRule)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 删除指定目录下的指定图片文件
     * @param contentsPath   目录路径
     * @param deleteImgNames 要删除的图片文件名列表（需包含扩展名）
     */
    public static void delContentsPathByFileName(String contentsPath, List<String> deleteImgNames) {
        // 参数校验
        if (contentsPath == null || contentsPath.isEmpty()) {
            log.warn("目录路径不能为空");
            return;
        }

        if (deleteImgNames == null || deleteImgNames.isEmpty()) {
            log.info("删除文件列表为空，无需操作");
            return;
        }

        Path dir = Paths.get(contentsPath);

        try {
            // 验证目录有效性
            if (!Files.exists(dir)) {
                log.warn("目录不存在: " + contentsPath);
                return;
            }
            if (!Files.isDirectory(dir)) {
                log.warn("路径不是目录: " + contentsPath);
                return;
            }

            // 转换为哈希集合提高查询效率
            Set<String> targetNames = new HashSet<>(deleteImgNames);

            // 使用NIO遍历目录（自动关闭流）
            try (Stream<Path> files = Files.list(dir)) {
                files.forEach(file -> {
                    try {
                        if (Files.isRegularFile(file)) {
                            String fileName = file.getFileName().toString();

                            // 判断是否需要删除
                            if (targetNames.contains(fileName)) {
                                Files.delete(file);
                                log.info("成功删除文件: " + file);
                            }
                        }
                    } catch (IOException e) {
                        log.warn("文件处理失败: " + file + " - " + e.getMessage());
                    }
                });
            }
        } catch (IOException e) {
            log.error("目录遍历异常: " + e.getMessage());
        }
    }
}




